﻿// Project: Salient
// http://salient.codeplex.com
// 
// Copyright 2010, Sky Sanders <sky at skysanders.net>
// Dual licensed under the MIT or GPL Version 2 licenses.
// http://salient.codeplex.com/license
// 
// Date: April 24 2010 

#region

using System;
using System.ComponentModel;
using System.Globalization;
using Microsoft.SqlServer.Types;

#endregion

namespace Salient.SqlServer.Types
{
    ///<summary>
    ///</summary>
    public class HierarchyIdTypeConverter : TypeConverter
    {
        /// <summary>
        ///                     Returns whether this converter can convert an object of the given type to the type of this converter, using the specified context.
        ///                 </summary>
        /// <returns>true if this converter can perform the conversion; otherwise, false.
        ///                 </returns>
        /// <param name="context">
        ///                     An <see cref="T:System.ComponentModel.ITypeDescriptorContext" /> that provides a format context. 
        ///                 </param>
        /// <param name="sourceType">
        ///                     A <see cref="T:System.Type" /> that represents the type you want to convert from. 
        ///                 </param>
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType == typeof (string) || sourceType == typeof (SqlHierarchyId))
            {
                return true;
            }

            return base.CanConvertFrom(context, sourceType);
        }

        /// <summary>
        ///                     Returns whether this converter can convert the object to the specified type, using the specified context.
        ///                 </summary>
        /// <returns>true if this converter can perform the conversion; otherwise, false.
        ///                 </returns>
        /// <param name="context">
        ///                     An <see cref="T:System.ComponentModel.ITypeDescriptorContext" /> that provides a format context. 
        ///                 </param>
        /// <param name="destinationType">
        ///                     A <see cref="T:System.Type" /> that represents the type you want to convert to. 
        ///                 </param>
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            if (destinationType == typeof (string) || destinationType == typeof (SqlHierarchyId))
            {
                return true;
            }

            return base.CanConvertTo(context, destinationType);
        }

        /// <summary>
        ///                     Converts the given object to the type of this converter, using the specified context and culture information.
        ///                 </summary>
        /// <returns>
        ///                     An <see cref="T:System.Object" /> that represents the converted value.
        ///                 </returns>
        /// <param name="context">
        ///                     An <see cref="T:System.ComponentModel.ITypeDescriptorContext" /> that provides a format context. 
        ///                 </param>
        /// <param name="culture">
        ///                     The <see cref="T:System.Globalization.CultureInfo" /> to use as the current culture. 
        ///                 </param>
        /// <param name="value">
        ///                     The <see cref="T:System.Object" /> to convert. 
        ///                 </param>
        /// <exception cref="T:System.NotSupportedException">
        ///                     The conversion cannot be performed. 
        ///                 </exception>
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            if (value is string)
            {
                return new HierarchyId((string) value);
            }
            if (value is SqlHierarchyId)
            {
                return new HierarchyId((SqlHierarchyId) value);
            }
            return base.ConvertFrom(context, culture, value);
        }

        /// <summary>
        ///                     Converts the given value object to the specified type, using the specified context and culture information.
        ///                 </summary>
        /// <returns>
        ///                     An <see cref="T:System.Object" /> that represents the converted value.
        ///                 </returns>
        /// <param name="context">
        ///                     An <see cref="T:System.ComponentModel.ITypeDescriptorContext" /> that provides a format context. 
        ///                 </param>
        /// <param name="culture">
        ///                     A <see cref="T:System.Globalization.CultureInfo" />. If null is passed, the current culture is assumed. 
        ///                 </param>
        /// <param name="value">
        ///                     The <see cref="T:System.Object" /> to convert. 
        ///                 </param>
        /// <param name="destinationType">
        ///                     The <see cref="T:System.Type" /> to convert the <paramref name="value" /> parameter to. 
        ///                 </param>
        /// <exception cref="T:System.ArgumentNullException">
        ///                     The <paramref name="destinationType" /> parameter is null. 
        ///                 </exception>
        /// <exception cref="T:System.NotSupportedException">
        ///                     The conversion cannot be performed. 
        ///                 </exception>
        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value,
                                         Type destinationType)
        {
            if (destinationType == typeof (string))
            {
                return value.ToString();
            }

            if (destinationType == typeof (SqlHierarchyId))
            {
                return ((HierarchyId) value).Inner;
            }
            return base.ConvertTo(context, culture, value, destinationType);
        }

        /// <summary>
        ///                     Returns whether the given value object is valid for this type and for the specified context.
        ///                 </summary>
        /// <returns>true if the specified value is valid for this object; otherwise, false.
        ///                 </returns>
        /// <param name="context">
        ///                     An <see cref="T:System.ComponentModel.ITypeDescriptorContext" /> that provides a format context. 
        ///                 </param>
        /// <param name="value">
        ///                     The <see cref="T:System.Object" /> to test for validity. 
        ///                 </param>
        public override bool IsValid(ITypeDescriptorContext context, object value)
        {
            if (value is string)
            {
                try
                {
                    SqlHierarchyId.Parse((string) value);
                    return true;
                }
                catch
                {
                    return false;
                }
            }
            if (value is SqlHierarchyId)
            {
                return true;
            }

            return base.IsValid(context, value);
        }
    }
}